<template>
  <div>
    <div class="shader-wrap" ref="shader"></div>
  </div>
</template>
<script>
import * as THREE from "three";
import { onMounted, ref, watch } from "vue";
window.THREE = THREE;
export default {
  name: "ShaderComponent",
};
</script>
<script setup>
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";

const props = defineProps({
  vertexShader: String, // 顶点着色器代码
  fragmentShader: String, // 片元着色器代码
});

const shader = ref(null);
onMounted(() => {
  const scene = new THREE.Scene({
    clearColor: 0x000000,
    // 抗锯齿
    antialias: true,
  });
  const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  camera.position.z = 5;
  // 创建渲染器
  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(800, 800);
  shader.value.appendChild(renderer.domElement);
  console.log("scene", scene);

  // 创建几何体
  var geometry = new THREE.PlaneGeometry(300, 150);
  //   var material = new THREE.MeshBasicMaterial({ color: 0xff0000, side: THREE.DoubleSide });
  // 创建着色器
  // 顶点着色器
  var vertexShader =
    props.vertexShader ||
    `
    void main() {
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `;
  const fragmentShader =
    props.fragmentShader ||
    `
    void main() {
      gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
    }
  `;
  const material = new THREE.ShaderMaterial({
    vertexShader: vertexShader,
    fragmentShader: fragmentShader,
    side: THREE.DoubleSide,
  });
  const mesh = new THREE.Mesh(geometry, material);
  mesh.position.set(0, 0, 0);
  scene.add(mesh);
  // 设置光源
  var ambientLight = new THREE.AmbientLight(0xcccccc);

  scene.add(ambientLight);
  // 设置相机位置并开始渲染循环
  camera.position.z = 100;
  camera.position.y = 50;
  camera.position.x = 0;
  camera.lookAt(0, 50, 100);
  const controls = new OrbitControls(camera, renderer.domElement);
  // 如果OrbitControls改变了相机参数，重新调用渲染器渲染三维场景
  // 监听鼠标、键盘事件
  controls.addEventListener("change", function () {
    renderer.render(scene, camera); //执行渲染操作
  });
  watch(
    () => [props.vertexShader, props.fragmentShader],
    ([newVertex, newFragment]) => {
      if (material && newVertex && newFragment) {
        material.vertexShader = newVertex;
        material.fragmentShader = newFragment;
        material.needsUpdate = true; // Important: tell Three.js to update the material
      }
    }
  );

  function animate() {
    requestAnimationFrame(animate);
    // 旋转立方体
    // mesh.rotation.x += 0.01;
    // mesh.rotation.y += 0.01;

    renderer.render(scene, camera);
  }
  animate();
});
</script>
<style scoped>
.shader-wrap {
  width: 800px;
  height: 800px;
}
</style>
